import { app, shell, BrowserWindow, ipcMain, Menu, dialog, nativeTheme } from 'electron'
import { download } from 'electron-dl'
import { join } from 'path'
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
import icon from '../../resources/icon.png?asset'
import sharp from 'sharp'
const { HttpsProxyAgent } = require('https-proxy-agent')
import {
  initializeDatabase,
  addUser,
  getUsers,
  editUser,
  loginUser,
  findUserByName,
  clearLogin,
  addTemp,
  editTemp,
  getTemps,
  addTask,
  editTask,
  getTasks,
  findUserByLogin,
  findAllMbs,
  updateUserYfmbByUsername,
  setShopName,
  getTaskById,
  getUserTaskByTaskId,
  canDoTaskUserIds,
  queryUserTaskWithPagination,
  stopUserTask,
  saveConfig,
  loadConfig,
  addUserTask,
  getTempById,
  getTaskProcess
} from './database'
import fs from 'fs'
import * as xlsx from 'xlsx'
import qs from 'qs'
import md5 from 'md5'
import { testProxyPool } from './proxyUtils'

let fetch = null;
(async () => {
  const nodeFetch = await import('node-fetch')
  fetch = nodeFetch.default
})()
const FormData = require('form-data')

class SequentialRequest {
  constructor() {
    this.queue = [] // 待请求的数据队列
    this.isProcessing = false // 是否正在处理中
    this.abortController = null // 当前请求的AbortController
    this.isStopped = false // 是否已停止
    this.callbacks = {
      // 回调函数集合
      onItemSuccess: null,
      onItemError: null,
      onAllComplete: null,
      onStop: null
    }
  }
  // 添加请求到队列（可选优先级）
  addRequest(data, priority = false) {
    if (this.isStopped) {
      console.warn('请求器已停止，请先调用resume()恢复')
      return
    }
    priority ? this.queue.unshift(data) : this.queue.push(data)
    if (!this.isProcessing) {
      this._processNext()
    }
  }
  // 根据条件删除队列中的请求
  removeRequest(conditionFn) {
    const initialLength = this.queue.length

    // 过滤掉匹配条件的数据
    this.queue = this.queue.filter((item) => !conditionFn(item))

    const removedCount = initialLength - this.queue.length
    if (removedCount > 0 && this.callbacks.onItemRemoved) {
      this.callbacks.onItemRemoved(removedCount)
    }

    return removedCount
  }
  // 根据ID删除特定请求
  removeById(id) {
    return this.removeRequest((item) => item.id === id)
  }
  // 获取当前队列状态
  getQueueStatus() {
    return {
      count: this.queue.length,
      items: [...this.queue] // 返回副本避免外部修改
    }
  }
  /** 处理下一个请求 */
  async _processNext() {
    if (this.isStopped || this.queue.length === 0) {
      this.isProcessing = false
      if (this.queue.length === 0 && this.callbacks.onAllComplete) {
        this.callbacks.onAllComplete()
      }
      return
    }
    this.isProcessing = true
    const data = this.queue.shift() // FIFO 先入先出
    this.abortController = new AbortController()
    try {
      const formData = new FormData()
      formData.append('productData', data.params)
      formData.append('itemId', data.good)
      const response = await fetch('http://127.0.0.1:9992/taobao/save', {
        method: 'POST',
        body: formData,
        signal: this.abortController.signal
      })
      if (!response.ok) throw new Error(`HTTP ${response.status}`)
      setTimeout(async () => {
        const result = await response.json()
        if (this.callbacks.onItemSuccess) {
          this.callbacks.onItemSuccess(data, result)
        }
        this._processNext() // 继续处理下一个
      }, 5000)
    } catch (error) {
      if (error.name === 'AbortError') {
        console.log('请求已终止')
      } else {
        console.error(`请求失败: ${error.message}`)
        if (this.callbacks.onItemError) {
          this.callbacks.onItemError(data, error)
        }
      }
    } finally {
      this.abortController = null
    }
  }
  /** 停止请求（并清空队列） */
  stop() {
    this.isStopped = true
    if (this.abortController) {
      this.abortController.abort()
    }
    this.queue = [] // 清空队列
    if (this.callbacks.onStop) {
      this.callbacks.onStop()
    }
  }
  // 清空指定任务的所有数据

  /** 恢复请求 */
  resume() {
    if (!this.isStopped) return
    this.isStopped = false
    this._processNext() // 重新启动处理器
  }
  /** 设置回调函数 */
  on(event, callback) {
    if (this.callbacks[event] !== undefined) {
      this.callbacks[event] = callback
    }
  }
}

const charCount = 4
let db = null
// 存储主窗口引用
let mainWindowRef = null
// 淘宝登录页面URL
let tbUrlLogin = 'https://login.taobao.com/havanaone/login/login.htm'
// 解码后的URL，确保loadURL能正确识别
let qnUrlLogin = 'https://item.upload.taobao.com/sell/v2/publish.htm?catId=121458010'

let uploadUrl = 'http://127.0.0.1:9992/taobao/img/upload'
// 配置压缩时是否删除原图
let sfscyt = false
let dev = false
const windows = new Map() // 使用 Map 存储窗口实例

const requestProcessor = new SequentialRequest()
// 设置回调
requestProcessor.on('onItemSuccess', (data, result) => {
  console.log(`✅ 成功提交数据 ${JSON.stringify(data)}`)
  console.log('响应数据:', result)

  db.run('update user_task set result = ?, zt = 1 where id = ?', [JSON.stringify(result), data.id])
})
requestProcessor.on('onItemError', (data, error) => {
  console.log(`❌ 提交失败 ${JSON.stringify(data)}`)
  console.error('错误信息:', error.message)
})
requestProcessor.on('onAllComplete', () => {
  console.log('🎉 所有请求完成！')
})
requestProcessor.on('onStop', () => {
  console.log('⏸️ 请求已停止，队列已清空')
})

function insertRandomChars(str, charCount = 4, types = ['letters', 'numbers']) {
  const chars = []
  const possible = {
    letters: 'abcdefghijklmnopqrstuvwxyz',
    numbers: '0123456789',
    symbols: '!@#$%^&*'
  }

  let pool = ''
  types.forEach((type) => (pool += possible[type] || ''))
  for (let i = 0; i < charCount; i++) {
    chars.push(pool[Math.floor(Math.random() * pool.length)])
  }
  const pos = Math.floor(Math.random() * (str.length + 1))
  return str.slice(0, pos) + chars.join('') + str.slice(pos)
}

async function dealwithText(good_detail, mbobj) {
  /** 基础配置 */
  // 新旧程度
  // 上架方式
  // 品牌更改
  if (mbobj.t1.ppgg == '无品牌/无注册商标') {
    let data = good_detail.properties
    const target = data.find((item) => item.key === '品牌')
    if (target) {
      target.value = ''
    }
    setDeep(good_detail, 'properties', data)
  } else if (mbobj.t1.ppgg == '自定义品牌') {
    let data = good_detail.properties
    const target = data.find((item) => item.key === '品牌')
    if (target) {
      target.value = mbobj.t1.zdyppmc
    }
    setDeep(good_detail, 'properties', data)
  }
  // 商家编码
  // 售后服务
  /** 标题配置 */
  // 添加前缀
  if (mbobj.t2.tjqz) {
    let name = mbobj.t2.tjqz + good_detail.goodsName
    setDeep(good_detail, 'goodsName', name)
  }
  // 添加后缀
  if (mbobj.t2.tjhz) {
    let name = mbobj.t2.tjhz + good_detail.goodsName
    setDeep(good_detail, 'goodsName', name)
  }
  // 超找替换内容
  if (mbobj.t2.cznr) {
    let name = good_detail.goodsName.replace(mbobj.t2.cznr, mbobj.t2.thnr)
    setDeep(good_detail, 'goodsName', name)
  }
  // 删除内容
  if (mbobj.t2.scnr) {
    let name = good_detail.goodsName.replace(mbobj.t2.scnr, '')
    setDeep(good_detail, 'goodsName', name)
  }
  // 删除标题前n字
  if (mbobj.t2.scbtq) {
    let n = Number.parseInt(mbobj.t2.scbtq)
    let len = good_detail.goodsName.length
    let name = ''
    if (n <= len) {
      name = good_detail.goodsName.slice(n)
    } else {
      name = good_detail.goodsName
    }
    setDeep(good_detail, 'goodsName', name)
  }
  // 删除标题后n字
  if (mbobj.t2.scbth) {
    let n = Number.parseInt(mbobj.t2.scbth)
    let len = good_detail.goodsName.length
    let name = ''
    if (n <= len) {
      name = good_detail.goodsName.slice(0, -n)
    } else {
      name = good_detail.goodsName
    }
    setDeep(good_detail, 'goodsName', name)
  }
  // 过滤sku名称长度不低于n字的商品
  // 是否删除【】内容
  if (mbobj.t2.sfsckhnr == '是') {
    let name = good_detail.goodsName.replace(/【[^】]*】/g, '')
    setDeep(good_detail, 'goodsName', name)
  }
  // 删除标题中的数字
  if (mbobj.t2.sfscbtsz == '是') {
    let name = good_detail.goodsName.replace(/[0-9]/g, '')
    setDeep(good_detail, 'goodsName', name)
  }
  // 删除标题中的空格
  if (mbobj.t2.sfscbtkg == '是') {
    let name = good_detail.goodsName.replace(/[\s\t\n\r]/g, '')
    setDeep(good_detail, 'goodsName', name)
  }
  // 删除标题中的字母
  if (mbobj.t2.sfscbtkg == '是') {
    let name = good_detail.goodsName.replace(/[a-zA-Z]/g, '')
    setDeep(good_detail, 'goodsName', name)
  }
  // 删除标题中随机插入字符
  if (mbobj.t2.sfscbtkg == '是') {
    let name = insertRandomChars(good_detail.goodsName, charCount, ['letters', 'numbers'])
    setDeep(good_detail, 'goodsName', name)
  }

  // 是否运行重复发布

  /////////////SKU配置///////////
  // 过滤sku价格低于多少的商品
  if (mbobj.t4.glskujgdy) {
    let price = Number.parseInt(mbobj.t4.glskujgdy)
    let skus = good_detail.skus
    let data = []
    skus.forEach((sku) => {
      if (sku.price >= price) {
        data.push(sku)
      }
    })
    // 过滤sku属性
    let props = good_detail.props[0].values
    let t1 = []
    data.forEach((sku) => {
      let vid = sku.id.split(':')[1]
      let prop = props.find((item) => item.vid === vid)
      t1.push(prop)
    })
    setDeep(good_detail, 'props[0].values', t1)
    setDeep(good_detail, 'skus', data)
  }
  // 过滤sku价格高于多少的商品
  if (mbobj.t4.glskujggy) {
    let price = Number.parseInt(mbobj.t4.glskujggy)
    let skus = good_detail.skus
    let data = []
    skus.forEach((sku) => {
      if (sku.price <= price) {
        data.push(sku)
      }
    })
    // 过滤sku属性
    let props = good_detail.props[0].values
    let t1 = []
    data.forEach((sku) => {
      let vid = sku.id.split(':')[1]
      let prop = props.find((item) => item.vid === vid)
      t1.push(prop)
    })
    setDeep(good_detail, 'props[0].values', t1)
    setDeep(good_detail, 'skus', data)
  }
  // 过滤sku库存低于多少的商品
  if (mbobj.t4.glskukcdy) {
    let quantity = Number.parseInt(mbobj.t4.glskukcdy)
    let skus = good_detail.skus
    let data = []
    skus.forEach((sku) => {
      if (sku.quantity >= quantity) {
        data.push(sku)
      }
    })
    // 过滤sku属性
    let props = good_detail.props[0].values
    let t1 = []
    data.forEach((sku) => {
      let vid = sku.id.split(':')[1]
      let prop = props.find((item) => item.vid === vid)
      t1.push(prop)
    })
    setDeep(good_detail, 'props[0].values', t1)
    setDeep(good_detail, 'skus', data)
  }
  // 过滤sku销量少于多少的商品
  // 过滤一口价少于多少的商品
  // 过滤一口价高于多少的商品
  // 过滤SKU名称包含的字符
  if (mbobj.t4.glskumzbh) {
    let props = good_detail.props[0].values
    let data = []
    props.forEach((item) => {
      if (!item.name.includes(mbobj.t4.glskumzbh)) {
        data.push(item)
      }
    })
    // 过滤sku
    let skus = []
    data.forEach((item) => {
      let sku = good_detail.skus.find((sku) => sku.id.split(':')[1] === item.vid)
      if (sku) {
        skus.push(sku)
      }
    })
    setDeep(good_detail, 'props[0].values', data)
    setDeep(good_detail, 'skus', skus)
  }
  // 加价策略
  if (mbobj.t7.cl) {
    let data = []
    mbobj.t7.cl.forEach((x) => {
      let start = Number.parseInt(x.k1)
      let end = Number.parseInt(x.k2)
      good_detail.skus.forEach((sku) => {
        if (x.k1 && x.k2 && x.k3 && x.k4 && x.k5 && x.k6 && x.k7 && x.k8) {
          if (sku.price >= start && sku.price <= end) {
            // 从新计算价格
            let p = 0
            if (x.k3 === '促销价') {
              p = randomAddOrSubtract(
                Number(sku.promotionPrice) * (Number(x.k4) / 100) + Number(x.k5),
                {
                  min: Number(x.k6),
                  max: Number(x.k7)
                }
              )
            } else if (x.k3 === '原价') {
              p = randomAddOrSubtract(
                Number(sku.originPrice) * (Number(x.k4) / 100) + Number(x.k5),
                {
                  min: Number(x.k6),
                  max: Number(x.k7)
                }
              )
            }
            if (x.k8 === '元') {
              p = toFixedDecimal(p, 0)
            } else if (x.k8 === '角') {
              p = toFixedDecimal(p, 1)
            } else if (x.k8 === '分') {
              p = toFixedDecimal(p, 2)
            }
            sku.price = p.toString()
            data.push(sku)
          }
        }
      })
    })
    let t = mergeArrays(good_detail.skus, data)
    setDeep(good_detail, 'skus', t)
  }
  return good_detail
}

async function renameFile(oldPath, newPath) {
  try {
    await fs.promises.rename(oldPath, newPath)
    // console.log('文件重命名成功！')
  } catch (err) {
    console.error('出错:', err)
  }
}
/**
 * 按路径设置值，同时支持：
 *   user.name
 *   users[0].name
 *   config.hosts[2].port
 */
function setDeep(obj, path, value) {
  // 1. 把 path 拆成 token：["users", 0, "name"]
  const tokens = path
    .replace(/[[\]]/g, (match) => (match === '[' ? '.' : '')) // [ → . , ] → 去掉
    .split('.') // 按 . 分割
    .filter(Boolean) // 排除空串

  let cur = obj
  for (let i = 0; i < tokens.length - 1; i++) {
    let key = tokens[i]
    key = isNaN(key) ? key : Number(key) // 数字转成索引

    // 若下一层不存在，根据再下一层 key 决定建 {} 还是 []
    if (cur[key] == null) {
      const next = tokens[i + 1]
      cur[key] = isNaN(next) ? {} : []
    }
    cur = cur[key]
  }

  // 最后一层赋值
  const last = tokens[tokens.length - 1]
  cur[isNaN(last) ? last : Number(last)] = value
}
async function uploadLocalFileToServer(filePath, fname, itemId) {
  try {
    // 构造 FormData 并上传
    const formData = new FormData()
    formData.append('itemId', itemId)
    formData.append('file', fs.createReadStream(filePath), fname) // 使用文件流上传

    const response = await fetch(uploadUrl, {
      method: 'POST',
      body: formData,
      headers: formData.getHeaders()
    })
    if (!response.ok) throw new Error('上传失败')
    const result = await response.json()
    return result
  } catch (err) {
    console.error('上传出错:', err)
    throw err
  }
}

async function dealWithPic(itemId, picUrl, tpysl, type) {
  const fileName = picUrl.substring(picUrl.lastIndexOf('/') + 1)
  console.log('dealWithPic', picUrl, tpysl, type, fileName)
  tpysl = tpysl || 0
  let downloadPath = await downloadImageWithProgress(picUrl, fileName)
  // 处理压缩
  let yst = ''
  if (tpysl) {
    let nPath = app.getPath('userData') + '/image/' + fileName
    await compressImage(downloadPath, nPath, tpysl) // 压缩 JPG 质量为 70
    yst = nPath
  }
  // 处理要上传的图片的名称
  let uploadImageLocalUrl = yst ? yst : downloadPath.replace('yt_', '')
  // 上传结果
  let result = null
  if (type == '主图') {
    let path = app.getPath('userData') + '/image/' + `${itemId}${fileName}ONETWOONE`
    let fname = `${itemId}${fileName}ONETWOONE`
    await renameFile(uploadImageLocalUrl, path)
    result = await uploadLocalFileToServer(path, fname, itemId)
  } else if (type == '主图3:4') {
    let path = app.getPath('userData') + '/image/' + `${itemId}${fileName}TTWOF`
    let fname = `${itemId}${fileName}TTWOF`
    await renameFile(uploadImageLocalUrl, path)
    result = await uploadLocalFileToServer(path, fname, itemId)
  } else {
    let fname = `${itemId}${fileName}`
    result = await uploadLocalFileToServer(uploadImageLocalUrl, fname, itemId)
  }
  // 返回单个链接
  return result.url || ''
}
//创建浏览器窗口
function createWindow() {
  // 创建主窗口
  const mainWindow = new BrowserWindow({
    width: 1400,
    height: 900,
    show: false,
    title: 'xxx系统',
    autoHideMenuBar: false,
    ...(process.platform === 'linux' ? { icon } : {}),
    webPreferences: {
      preload: join(__dirname, '../preload/index.js'),
      sandbox: false,
      enableRemoteModule: true
    }
  })

  // Create menu template
  const menuTemplate = [
    {
      label: '帮助',
      click: () => {
        mainWindow.webContents.send('navigate', '/help')
      }
    },
    // {
    //   label: '关于',
    //   submenu: [
    //     {
    //       label: '首页',
    //       click: () => {
    //         mainWindow.webContents.send('navigate', '/')
    //       }
    //     },
    //     {
    //       label: '关于',
    //       click: () => {
    //         mainWindow.webContents.send('navigate', '/about')
    //       }
    //     },
    //     {
    //       label: '上传文件',
    //       click: () => {
    //         mainWindow.webContents.send('navigate', '/upload')
    //       }
    //     }
    //   ]
    // },
    // {
    //   label: '演示',
    //   submenu: [
    //     {
    //       label: '显示Hello',
    //       click: async () => {
    //         try {
    //           // 尝试添加用户，如果email已存在会抛出错误
    //           await addUser(db, 'aaaaaa1', 'ccccccccc123')
    //           console.log('用户添加成功')
    //         } catch (error) {
    //           if (error.message.includes('SQLITE_CONSTRAINT')) {
    //             console.log('该邮箱已存在，无法重复添加用户')
    //           } else {
    //             console.error('添加用户失败:', error)
    //           }
    //         }
    //         mainWindow.webContents.send('show-hello', 'Hello World')
    //       }
    //     }
    //   ]
    // },
    {
      label: '系统设置',
      submenu: [
        {
          label: '设置类目数据',
          click: async () => {
            mainWindow.webContents.send('navigate', '/editClass')
          }
        },
        {
          label: '设置地址数据',
          click: async () => {
            mainWindow.webContents.send('navigate', '/editAddress')
          }
        },
        {
          label: '设置全局配置',
          click: async () => {
            mainWindow.webContents.send('setting')
          }
        },
        {
          label: '关于',
          click: () => {
            mainWindow.webContents.send('navigate', '/about')
          }
        }
      ]
    }
    // {
    //   label: '系统设置',
    //   click: async () => {
    //     try {
    //       // 获取当前是否为深色模式
    //       const isDarkMode = nativeTheme.shouldUseDarkColors

    //       // 显示对话框让用户选择是否使用深色模式
    //       const { response, checkboxChecked } = await dialog.showMessageBox(mainWindow, {
    //         type: 'question',
    //         title: '系统设置',
    //         message: '是否启用深色模式？',
    //         buttons: ['取消', '确定'],
    //         defaultId: isDarkMode ? 1 : 0,
    //         checkboxLabel: '使用深色模式',
    //         checkboxChecked: isDarkMode
    //       })

    //       // 如果用户点击了确定，或者取消但更改了复选框状态
    //       if (response === 1 || (response === 0 && checkboxChecked !== isDarkMode)) {
    //         // 设置深色模式
    //         nativeTheme.themeSource = checkboxChecked ? 'dark' : 'light'
    //         console.log('深色模式已', checkboxChecked ? '启用' : '禁用')

    //         // 通知所有窗口主题已更改
    //         BrowserWindow.getAllWindows().forEach((window) => {
    //           window.webContents.send('theme-changed', checkboxChecked)
    //         })
    //       }
    //     } catch (error) {
    //       console.error('打开系统设置对话框失败:', error)
    //     }
    //   }
    // }
  ]

  // Set menu
  const menu = Menu.buildFromTemplate(menuTemplate)
  Menu.setApplicationMenu(menu)

  // 保存主窗口引用
  mainWindowRef = mainWindow

  // 监听主窗口关闭事件
  mainWindow.on('closed', () => {
    clearLoginUserStatus()
    console.log('主窗口已关闭，正在关闭所有子窗口...')

    // 关闭所有子窗口
    for (let key of windows.keys()) {
      let window = windows.get(key)
      if (window && !window.isDestroyed()) {
        window.close()
      }
      windows.delete(key)
    }
    // 清空主窗口引用
    mainWindowRef = null
  })

  mainWindow.on('ready-to-show', () => {
    mainWindow.show()
  })

  mainWindow.webContents.setWindowOpenHandler((details) => {
    shell.openExternal(details.url)
    return { action: 'deny' }
  })

  // HMR for renderer base on electron-vite cli.
  // Load the remote URL for development or the local html file for production.
  if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
    mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
  } else {
    mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
  }

  // mainWindow.webContents.openDevTools()
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
const { antiPacketCapture } = require('./anti-debug')

async function downloadImageWithProgress(url, filename) {
  try {
    const downloadItem = await download(mainWindowRef, url, {
      directory: app.getPath('userData') + '/image/', // 保存目录
      filename: `yt_${filename}`, // 自定义文件名
      onProgress: (progress) => {
        // console.log(`下载进度：${Math.floor(progress.percent * 100)}%`)
      },
      // 可选：下载完成回调
      onCompleted: (file) => {
        // console.log('✅ 文件下载完成：', file.path) // 文件路径
      },
      showBadge: true, // 是否在 Dock/Taskbar 显示下载进度
      saveAs: false // 是否弹出“另存为”对话框
    })
    return downloadItem.getSavePath()
  } catch (err) {
    console.error('❌ 下载失败:', err)
    throw err
  }
}
async function compressImage(inputPath, outputPath, quality = 10) {
  try {
    const inputMetadata = await sharp(inputPath).metadata()
    const isJpeg = inputMetadata.format === 'jpeg' || inputMetadata.format === 'jpg'

    const sharpInstance = sharp(inputPath).withMetadata(false)

    if (isJpeg) {
      sharpInstance.jpeg({
        quality: Math.max(10, quality), // 确保最低质量10
        mozjpeg: true
      })
    } else if (inputMetadata.format === 'png') {
      sharpInstance.png({
        compressionLevel: 9, // 最大压缩
        palette: true // 启用调色板优化
      })
    }

    await sharpInstance.toFile(outputPath)
    console.log('图片压缩成功:', outputPath)

    // 检查压缩结果
    const outputStats = fs.statSync(outputPath)
    const inputStats = fs.statSync(inputPath)

    if (sfscyt && outputStats.size < inputStats.size) {
      // 仅当压缩后文件更小时才删除原图
      const path = require('path')
      if (path.resolve(inputPath) === path.resolve(outputPath)) {
        throw new Error('输入和输出路径不能相同！')
      }
      await fs.promises.unlink(inputPath) // 删除原图
      console.log('原图已删除:', inputPath)
    }
  } catch (error) {
    outputPath = inputPath
    console.error('压缩失败:', error)
  }
}

app.whenReady().then(() => {
  // 检测抓包软件
  antiPacketCapture()

  db = initializeDatabase()

  // 清除登录信息
  clearLoginUserStatus()

  // 处理模板下载请求
  ipcMain.handle('down-template', async () => {
    try {
      // 模板文件路径
      const templatePath = path.join(__dirname, '../../resources/店铺导入模板.xlsx')

      // 检查文件是否存在
      if (!fs.existsSync(templatePath)) {
        throw new Error('模板文件不存在')
      }

      // 打开保存对话框
      const result = await dialog.showSaveDialog({
        title: '保存店铺导入模板',
        defaultPath: '店铺导入模板.xlsx',
        filters: [{ name: 'Excel 文件', extensions: ['xlsx'] }]
      })

      if (result.canceled) {
        throw new Error('用户取消保存')
      }

      // 读取模板文件内容
      const fileContent = fs.readFileSync(templatePath)

      // 写入到用户选择的路径
      fs.writeFileSync(result.filePath, fileContent)

      console.log('模板下载成功:', result.filePath)
    } catch (error) {
      console.error('模板下载失败:', error)
      throw error
    }
  })

  // 设置 IPC 通信
  ipcMain.handle('add-user', async (event, { name, email }) => {
    return await addUser(db, name, email)
  })
  ipcMain.handle('edit-user', async (event, { name, pwd, id }) => {
    return await editUser(db, name, pwd, id)
  })

  ipcMain.handle('get-users', async (event, { page = 1, pageSize = 10, keyword = '' } = {}) => {
    return await getUsers(db, { page, pageSize, keyword })
  })

  ipcMain.handle('get-login', async () => {
    return await findUserByLogin(db)
  })

  ipcMain.handle('add-temp', async (event, { name, str }) => {
    return await addTemp(db, name, str)
  })
  ipcMain.handle('edit-temp', async (event, { id, name, str }) => {
    return await editTemp(db, name, str, id)
  })

  ipcMain.handle('get-temps', async (event, { page = 1, pageSize = 10, keyword = '' } = {}) => {
    return await getTemps(db, { page, pageSize, keyword })
  })

  ipcMain.handle('setting-yfmb', async (event, { shop_id, yfmb } = {}) => {
    return await updateUserYfmbByUsername(db, shop_id, yfmb)
  })

  ipcMain.handle('get-all-mbs', async () => {
    return await findAllMbs(db)
  })

  ipcMain.handle('get-usertask', async (event, { uid, task_id, page = 1, pageSize = 10 } = {}) => {
    return await queryUserTaskWithPagination(db, { uid, task_id, page, pageSize })
  })

  ipcMain.handle('add-task', async (event, { path: filePath, name, mbs, shops }) => {
    // 获取模版详情
    let oneTemp = await getTempById(db, mbs)
    if (!oneTemp) {
      throw new Error('模版不存在')
    }
    let mbDetail = JSON.parse(oneTemp.content)
    let tpysl = mbDetail.t5.tpysl // 图片压缩率
    let sfsc34zt = mbDetail.t5.sfsc34zt // 是否上传3:4主图
    let sfztbwxqt = mbDetail.t5.sfztbwxqt // 详情为空，是否主图作为详情图
    let sfscskut = mbDetail.t5.sfscskut // 是否上传sku图
    console.log('模版详情', mbDetail)
    const fileExtension = filePath.split('.').pop().toLowerCase()
    let content = ''
    if (fileExtension === 'txt') {
      // 读取txt文件
      let temp = fs.readFileSync(filePath, 'utf8')
      content = temp.replace(/\r\n/g, ',')
    } else if (['xlsx', 'xls'].includes(fileExtension)) {
      // 读取excel文件
      const workbook = xlsx.readFile(filePath)
      const firstSheetName = workbook.SheetNames[0]
      const worksheet = workbook.Sheets[firstSheetName]
      const jsonData = xlsx.utils.sheet_to_json(worksheet, { header: 1 })
      content = jsonData.flat().join(',')
    }

    let taskId = await addTask(db, content, name, shops, mbs)
    console.log('任务添加成功！', taskId)

    // 获取数据库路径
    const dbPath = path.join(app.getPath('userData'), 'electron-vite.db')
    try {
      console.log(`开始执行任务，任务ID: ${taskId}`)
      let task = await getTaskById(db, taskId)
      console.log('任务信息:', task)
      if (task) {
        if (task.result == '0') {
          console.log('需要分配任务')
          let users = task.shops.split(',')
          let mb = task.mbs
          let content = task.task
          // 导入worker_threads模块
          const { Worker } = require('worker_threads')
          const path = require('path')

          // content的内容是网址字符串，现在需要将content均匀的分配给每个用户，使用多线程去写入数据库
          const urls = content.split(',').filter((url) => url.trim()) // 分割网址并过滤空行
          const userCount = users.length // 用户个数
          const urlsPerUser = Math.ceil(urls.length / userCount) // 每个用户分配到网址的个数

          // 按照用户分配网址
          let userDatas = []
          for (let i = 0; i < userCount; i++) {
            const startIndex = i * urlsPerUser
            const endIndex = startIndex + urlsPerUser
            const userUrls = urls.slice(startIndex, endIndex)
            userDatas.push({
              userId: users[i],
              urls: userUrls,
              taskId: taskId,
              mb: mb
            })
          }
          console.log(`任务分配结果: 分配 ${JSON.stringify(userDatas)}`)
          // 分配线程
          const workerCount = 1 // 使用worker数量和用户数一直
          const workers = []

          // 创建多个workers
          for (let i = 0; i < workerCount; i++) {
            try {
              console.log(`[主线程] 创建Worker ${i} 开始`)
              const worker = new Worker(path.join(__dirname, 'batchTaskWorker.js'), {
                workerData: {
                  dbPath: dbPath
                }
              })
              worker.id = i
              console.log(`[主线程] Worker ${i} 创建成功, 线程ID:`, worker.threadId || '未知')

              worker.on('message', async (result) => {
                console.log('[主线程] 收到 worker 计算结果:', result)

                // 写入数据库中
                for (let i = 0; i < result.result.length; i++) {
                  let t = result.result[i]
                  let good_detail = JSON.parse(t.result)
                  ///////////////////////////////////////////////////////////////////////
                  // 处理文字信息
                  let obj = await dealwithText(good_detail, mbDetail)
                  good_detail = obj
                  // // 处理mainImages
                  // let mainImages = good_detail.mainImages

                  // let x = []
                  // for (let index = 0; index < mainImages.length; index++) {
                  //   const element = mainImages[index]
                  //   let res = await dealWithPic(good_detail.itemId, element, tpysl, '主图')
                  //   x.push(res)
                  // }
                  // setDeep(good_detail, 'mainImages', x)
                  // let y = []
                  // // 处理DescUrl
                  // let DescUrl = good_detail.DescUrl
                  // for (let index = 0; index < DescUrl.length; index++) {
                  //   const element = DescUrl[index]
                  //   let res = await dealWithPic(good_detail.itemId, element, tpysl, '其它')
                  //   y.push(res)
                  // }
                  // setDeep(good_detail, 'DescUrl', y)

                  // // 处理props中的图片
                  // let z = []
                  // let propsImg = good_detail.props[0].values
                  // if (propsImg) {
                  //   console.log('propsImg', propsImg.length)
                  //   for (let index = 0; index < propsImg.length; index++) {
                  //     const element = propsImg[index]
                  //     if (element.image) {
                  //       let res = await dealWithPic(
                  //         good_detail.itemId,
                  //         element.image,
                  //         tpysl,
                  //         '其它'
                  //       )
                  //       z.push({
                  //         ...element,
                  //         image: res
                  //       })
                  //     }
                  //   }
                  //   console.log('========>', JSON.stringify(z))
                  //   setDeep(good_detail, 'props[0].values', z)
                  // }

                  const newJsonStr = JSON.stringify(good_detail)

                  addUserTask(db, t.taskId, t.task_url, t.userId, t.mb, newJsonStr, '')
                    .then((id) => {
                      console.log('addUserTask:', id)
                    })
                    .catch((err) => {
                      console.log('addUserTask err:', err)
                    })
                }

                // if (mainWindow && !mainWindow.isDestroyed()) {
                //   mainWindow.webContents.send('worker-result', result)
                // }
              })

              worker.on('error', (error) => {
                console.error(`[主线程] Worker ${i} 发生错误:`, error)
              })

              worker.on('exit', (code) => {
                console.log(`[主线程] Worker ${i} 已退出, 退出码: ${code}`)
              })

              workers.push(worker)
              console.log(`[主线程] Worker ${i} 已添加到workers数组`)
            } catch (error) {
              console.error(`[主线程] 创建Worker ${i} 失败:`, error)
            }
          }

          // 分配任务给每个worker
          console.log(`[主线程] 开始给${workers.length}个worker分配任务`)
          workers.forEach((worker, index) => {
            const workerData = {
              id: index,
              value: userDatas[index] || {}
            }
            console.log(
              `[主线程] 给Worker ${index} 分配任务, 用户ID: ${userDatas[index]?.userId || '未知'}`
            )
            console.log(
              `[主线程] Worker ${index} postMessage前的状态:`,
              worker.threadId ? '活跃' : '不活跃'
            )
            try {
              worker.postMessage(workerData)
              console.log(`[主线程] 成功向Worker ${index} 发送任务`)
            } catch (error) {
              console.error(`[主线程] 向Worker ${index} 发送任务失败:`, error)
            }
          })

          // 记录任务分配日志
          console.log(`任务 ${taskId} 已分配给用户：${users}，使用模板：${mb}`)
        }
        if (task.result == '1') {
          console.log('已分配任务，需要开始执行任务')
        }
      }
      return {
        success: true,
        message: `任务 ${taskId} 已成功启动`,
        taskId: taskId
      }
    } catch (error) {
      console.error(`启动任务失败: ${error.message}`)
      return {
        success: false,
        message: `启动任务失败: ${error.message}`,
        error: error.message
      }
    }
  })

  ipcMain.handle('edit-task', async (event, { id, name, str }) => {
    return await editTask(db, name, str, id)
  })

  ipcMain.handle('get-tasks', async (event, { page = 1, pageSize = 10, keyword = '' } = {}) => {
    let data = await getTasks(db, { page, pageSize, keyword })

    if (data.total > 0) {
      let task1 = []
      for (let index = 0; index < data.tasks.length; index++) {
        const element = data.tasks[index]
        let task_id = element.id
        let process = await getTaskProcess(db, task_id)
        element.process = process
        task1.push(element)
      }

      data.tasks = task1
    }
    return data
  })
  // 停止任务
  ipcMain.handle('stop-task', async (event, { taskId }) => {
    console.log('初始队列:', requestProcessor.getQueueStatus().items)
    // 示例1：删除特定ID的任务
    // processor.removeById(4) // 删除id为4的任务
    // 示例2：使用条件函数删除
    requestProcessor.removeRequest((item) => item.task_id == taskId)
    // 示例3：获取当前队列
    console.log('当前队列:', requestProcessor.getQueueStatus().items)
    // 通知数据库暂停任务
    return await stopUserTask(db, taskId)
  })

  // 启动任务
  ipcMain.handle('start-task', async (event, { taskId }) => {
    console.log('开始启动任务:', taskId)
    // 获取数据库路径
    const dbPath = path.join(app.getPath('userData'), 'electron-vite.db')
    // 获取已登录的所有用户
    let users = await findUserByLogin(db)
    // 查看任务是否可运行
    let task = await getTaskById(db, taskId)
    if (task.result == '3') {
      return { success: false, message: `任务 ${taskId} 已完成！` }
    } else if (task.result == '0' || task.result == '1') {
      // 执行任务,使用多线程提交数据
      let userTasks = await getUserTaskByTaskId(
        db,
        taskId,
        users.map((item) => item.id)
      )
      userTasks.forEach((x) => {
        console.log('add task queue:', x)
        requestProcessor.addRequest(x)
      })

      // let uids = await canDoTaskUserIds(
      //   db,
      //   taskId,
      //   users.map((item) => item.id)
      // )
      // const grouped = userTasks.reduce((acc, item) => {
      //   if (!acc[item.uid]) {
      //     acc[item.uid] = [] // 每个 uid 对应一个数组
      //   }
      //   acc[item.uid].push(item) // 添加到对应的 uid 组
      //   return acc
      // }, {})
      // console.log('grouped:', grouped)

      // 分配线程
      // 导入worker_threads模块
      // const { Worker } = require('worker_threads')
      // const path = require('path')
      // const workers = []
      // const results = []
      // const userDatas = []
      // // 创建多个workers
      // for (let i = 0; i < uids.length; i++) {
      //   userDatas.push({
      //     uid: uids[i].uid,
      //     tasks: grouped[uids[i].uid],
      //     cookie: users.filter((item) => item.id == uids[i].uid)[0].cookie
      //   })
      //   const worker = new Worker(path.join(__dirname, 'batchTaskSubmitTbWorker.js'), {
      //     workerData: {
      //       dbPath: dbPath
      //     }
      //   })
      //   worker.id = i

      //   worker.onmessage = function (e) {
      //     console.log('来自子线程的消息：', e.data)
      //     results[e.data.id] = e.data.result
      //     console.log(`Worker ${e.data.id} 完成, 结果: ${e.data.result}`)

      //     // 检查是否所有worker都完成了
      //     if (results.filter(Boolean).length === uids.length) {
      //       const finalResult = results.reduce((sum, val) => sum + val, 0)
      //       console.log('所有worker完成, 最终结果:', finalResult)
      //     }
      //   }

      //   workers.push(worker)
      // }
      // console.log('开始分配任务给worker...', workers.length)
      // // 分配任务给每个worker
      // workers.forEach((worker, index) => {
      //   console.log(`分配任务给worker ${index}`)
      //   worker.postMessage({ id: index, value: userDatas[index] })
      // })
    } else {
      console.log('任务已执行或正在执行中...')
      return { success: false, message: `任务 ${taskId} 已执行或正在执行中` }
    }
  })

  // Set app user model id for windows
  electronApp.setAppUserModelId('com.electron')

  // Default open or close DevTools by F12 in development
  // and ignore CommandOrControl + R in production.
  // see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
  app.on('browser-window-created', (_, window) => {
    optimizer.watchWindowShortcuts(window)
  })
  // IPC test
  ipcMain.on('ping', async (event, data) => {
    console.log('pong', data)
    // 使用示例
    const proxyList = [
      'http://121.224.230.71:2324',
      'http://121.224.230.71:12324',
      'http://121.224.230.71:2324'
    ]

    testProxyPool(proxyList).then((res) => {
      let result1 = {
        total: 3,
        working: 2,
        failed: 1,
        workingProxies: ['http://121.224.230.71:2324', 'http://121.224.230.71:2324'],
        failedProxies: ['http://121.224.230.71:12324'],
        successRate: '66.67%'
      }
      console.log('res', res, result1)
    })
    // //这里是访问的路径
    // let url = 'http://120.70.103.78:9200/users'
    // //这是代理服务器地址
    // let ip = '180.121.218.134'
    // //这是端口号
    // let port = '23018'
    // fetch(url, {
    //   method: 'GET',
    //   // body: null,
    //   agent: new HttpsProxyAgent('http://' + ip + ':' + port) // 正确用法：直接使用导入的构造函数
    // })
    //   .then(function (res) {
    //     console.log('Response Headers ============ ')
    //     res.headers.forEach(function (v, i, a) {
    //       console.log(i + ' : ' + v)
    //     })
    //     return res.text()
    //   })
    //   .then(function (res) {
    //     console.log('Response Body ============ ')
    //     console.log(res)
    //   })
  })
  ipcMain.on('open-tb-address', async (event, data) => {
    console.log('open-tb-address', data)
    windows
      .get('15510007550')
      .loadURL(
        'https://adpmanager.taobao.com/user/template_setting.htm?pageVersion=V2&toolAuth=cm-tool-manage'
      )
  })

  // 打开多个窗口示例
  function openMoreWindow(params = []) {
    mainWindowRef = BrowserWindow.getFocusedWindow()
    if (!mainWindowRef) {
      console.error('无法获取主窗口引用')
    } else {
      console.log('已获取主窗口引用')
    }
    // 创建3个窗口，每个窗口都访问百度
    for (let i = 0; i < params.length; i++) {
      // 获取当前窗口的参数，如果没有提供则使用默认值
      const windowParams = params[i]
      const { name: username, pwd: password } = windowParams
      // 为每个窗口设置不同的位置，避免重叠
      const offsetX = 100 + i * 200
      const offsetY = 100 + i * 100

      const taobaoWindow = new BrowserWindow({
        width: 800,
        height: 600,
        x: offsetX,
        y: offsetY,
        show: true,
        // headless: true,
        autoHideMenuBar: true,
        title: '淘宝登录',
        webPreferences: {
          sandbox: false,
          enableRemoteModule: true,
          nodeIntegration: false,
          contextIsolation: true,
          preload: join(__dirname, '../preload/index.js'),
          // 添加浏览器特征
          userAgent:
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
          webSecurity: false,
          allowRunningInsecureContent: true
        }
      })
      windows.set(username, taobaoWindow)

      // 确保菜单栏被隐藏
      taobaoWindow.setMenuBarVisibility(false)
      taobaoWindow.setAutoHideMenuBar(true)

      // 打开网页前清除所有记录、cookie和session
      taobaoWindow.webContents.session
        .clearStorageData()
        .then(() => {
          console.log('已清除存储数据')
          taobaoWindow.webContents.session
            .clearCache()
            .then(() => {
              console.log('已清除缓存')
              // 加载淘宝登录页面
              taobaoWindow.loadURL(tbUrlLogin)
            })
            .catch((err) => {
              console.error('清除缓存失败:', err)
            })
        })
        .catch((err) => {
          console.error('清除存储数据失败:', err)
        })

      // 页面加载完成后模拟登录
      taobaoWindow.webContents.on('did-finish-load', (event, url) => {
        const currentURL = taobaoWindow.webContents.getURL()
        console.log('当前加载完成的地址:', currentURL)
        if (currentURL.includes('/login/login.htm')) {
          taobaoWindow.webContents
            .executeJavaScript(
              `
        // 等待DOM元素加载完成
        setTimeout(() => {
          // 模拟输入账号密码
          document.getElementById('fm-login-id').value = '${username || ''}';
          document.getElementById('fm-login-password').value = '${password || ''}';

          // 模拟点击登录按钮
          document.querySelector('.fm-button').click();
        }, 1000);
      `
            )
            .then(() => {
              console.log('已尝试模拟登录')
            })
            .catch((err) => {
              console.error('模拟登录失败:', err)
            })
        } else if (currentURL.includes('my.taobao.com')) {
          console.log('当前页面为淘宝卖家页面')
        } else if (currentURL.includes('/sell/v2/publish.htm')) {
          // 加载数据
          taobaoWindow.webContents
            .executeJavaScript(
              `
              let result = null;
              try {
                // 安全地访问嵌套对象
                if (window.Json && window.Json.components && window.Json.components.tbExtractWay && window.Json.components.tbExtractWay.props) {
                  console.log('开始获取数据', window.Json.components.tbExtractWay.props.subItems);
                  result = window.Json.components.tbExtractWay.props.subItems;
                } else {
                  console.error('window.Json或其属性不存在');
                }
              } catch (error) {
                console.error('获取数据时发生错误:', error);
              }
              result; // 返回结果
            `
            )
            .then((data) => {
              // 把数据写入到数据库中
              // url encode data.cookie
              updateUserYfmbByUsername(db, username, JSON.stringify(data))
                .then((res) => {
                  console.log('写入数据库成功', res)
                })
                .catch((err) => {
                  console.log('写入数据库失败', err)
                })
              if (data) {
                // 在这里可以使用获取到的数据
                mainWindowRef.webContents.send('tb-data', data)
              }
            })
            .catch((err) => {
              console.error('err:', err)
            })
          taobaoWindow.webContents.session.cookies
            .get({ domain: '.taobao.com' })
            .then((cookies) => {
              console.log('成功获取cookies，数量:', cookies.length)
              // 判断cookies中是否存在_m_h5_tk
              const hasMH5Tk = cookies.some((cookie) => cookie.name === '_m_h5_tk')
              console.log('_m_h5_tk存在状态:', hasMH5Tk)
              if (hasMH5Tk) {
                console.log('找到了 _m_h5_tk，准备发送cookie数据')
                // 发送cookie数据到渲染进程
                let cookiesStr = ''
                cookies.forEach((cookie) => {
                  // console.log(`${cookie.name},${cookie.value}`)
                  cookiesStr += `${cookie.name}=${cookie.value};`
                })
                // 直接写入到用户表
                loginUser(db, username, cookiesStr.slice(0, -1))

                // 更新用户店铺名称
                findUserByName(db, username)
                  .then((res) => {
                    console.log('用户数据：', JSON.stringify(res))
                    if (res.length > 0 && res[0].shop_name === null) {
                      getShopNameByNet(res[0]).then((shopName) => {
                        console.log('shopName:', shopName.data.data.module.shopTitle)
                        setShopName(db, res[0].name, shopName.data.data.module.shopTitle)
                      })
                    }
                  })
                  .finally(() => {
                    // 使用之前存储的主窗口引用发送cookie数据
                    if (mainWindowRef) {
                      mainWindowRef.webContents.send('tbcookie', cookies)
                      console.log('cookie数据已发送到主窗口')
                      // 隐藏窗口，后续刷新更新cookie数据
                      // taobaoWindow.hide()
                    } else {
                      console.error('主窗口引用不存在，无法发送cookie数据')
                      // 尝试再次获取主窗口
                      const fallbackWindow = BrowserWindow.getAllWindows()[0]
                      if (fallbackWindow) {
                        fallbackWindow.webContents.send('tbcookie', cookies)
                        console.log('使用备用方式发送cookie数据到主窗口')
                      } else {
                        console.error('无法找到任何窗口发送cookie数据')
                      }
                    }
                  })
                // 关闭窗口
                // taobaoWindow.close()
              } else {
                console.log('未找到 _m_h5_tk')
                taobaoWindow.webContents.reload()
                return
              }
            })
            .catch((err) => {
              console.error('获取Cookie失败:', err)
            })
        } else if (
          currentURL.includes('https://qn.taobao.com/home.htm/consign-tools-group/freightTemplate')
        ) {
          console.log('当前页面为运费模板设置')
          // 隐藏窗口
          taobaoWindow.hide()
        }
      })

      // 监听页面跳转，获取cookie
      taobaoWindow.webContents.on('did-navigate', (event, url) => {
        console.log('已跳转到发布页面', url)
        if (url.includes('my_taobao.htm')) {
          // 添加延迟以确保跳转执行
          setTimeout(() => {
            console.log('跳转后当前URL:', taobaoWindow.webContents.getURL())
            console.log('已进入淘宝页面，准备跳转到发布页')
            console.log('跳转URL:', qnUrlLogin)
            taobaoWindow.loadURL(qnUrlLogin)
          }, 2000)
        } else {
          console.log('URL不匹配')
        }
      })

      // 当窗口关闭时的处理，监听子窗口关闭事件，从列表中移除
      taobaoWindow.on('closed', () => {
        deleteByValue(windows, taobaoWindow)
      })

      // 三秒后隐藏窗口
      // setTimeout(() => {
      //   console.log(`隐藏窗口 ${i + 1}`)
      //   taobaoWindow.hide()
      // }, 3000)

      // 每分钟刷新页面
      // setInterval(() => {
      //   console.log(`刷新窗口 ${i + 1} 页面`)
      //   taobaoWindow.reload()
      // }, 60000)

      // 添加加载失败错误处理
      taobaoWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription) => {
        console.error(`窗口 ${i + 1} 加载失败: ${errorDescription} (错误码: ${errorCode})`)
      })

      // 添加加载成功日志，然后每次去保存cookie数据
      taobaoWindow.webContents.on('did-finish-load', () => {
        console.log(`窗口 ${i + 1} 加载成功`)
      })
    }
  }

  // 监听打开多窗口的请求
  ipcMain.on('open-more-window', (event, params) => {
    let login = JSON.parse(params)
    openMoreWindow(login)
  })

  // Handle navigation from renderer
  ipcMain.on('navigate', (event, path) => {
    console.log('navigate:', path)
    const mainWindow = BrowserWindow.getFocusedWindow()
    if (mainWindow) {
      mainWindow.webContents.send('navigate', path)
    }
  })

  // 导入 worker_threads 模块
  const { Worker } = require('worker_threads')
  const path = require('path')

  // 用于跟踪工作线程的集合
  const workers = new Set()

  // 处理文件解析 - 使用多线程
  ipcMain.on('parse-txt-file', (event, data) => {
    console.log('开始解析TXT文件...')
    const { lines } = data
    const lineCount = lines.length

    // 如果行数较少，直接在主线程处理
    if (lineCount < 2) {
      // 模拟耗时操作
      const startTime = Date.now()
      console.log('行数较少，直接在主线程处理')
      lines.forEach((line, index) => {
        console.log(`行 ${index + 1}: ${line}`)
      })
      event.reply('txt-file-parsed', { success: true, lineCount: lineCount })
      const endTime = Date.now()
      console.log(`工作线程解析完成，耗时: ${endTime - startTime}ms`)
      return
    }

    // 行数较多，使用多线程处理
    console.log(`行数较多(${lineCount})，使用多线程处理`)

    // 确定线程数量（根据CPU核心数和文件大小调整）
    const numThreads = Math.min(require('os').cpus().length, Math.ceil(lineCount / 10000))
    console.log(`将使用 ${numThreads} 个线程进行解析`)

    // 计算每个线程处理的行数
    const linesPerThread = Math.ceil(lineCount / numThreads)
    let completedThreads = 0
    let allResults = []

    // 创建工作线程
    for (let i = 0; i < numThreads; i++) {
      const start = i * linesPerThread
      const end = Math.min(start + linesPerThread, lineCount)
      const threadLines = lines.slice(start, end)

      const worker = new Worker(path.join(__dirname, 'worker.js'))
      workers.add(worker)

      // 监听工作线程消息
      worker.on('message', (message) => {
        if (message.ready) {
          // 工作线程就绪，发送数据
          worker.postMessage({ lines: threadLines })
        } else if (message.success) {
          // 收集结果
          allResults = allResults.concat(message.results)
          completedThreads++

          // 所有线程完成
          if (completedThreads === numThreads) {
            console.log('所有线程解析完成，共处理 ' + allResults.length + ' 行')
            event.reply('txt-file-parsed', {
              success: true,
              lineCount: lineCount,
              resultCount: allResults.length,
              data: allResults
            })

            // 清理工作线程
            workers.forEach((worker) => worker.terminate())
            workers.clear()
          }
        }
      })

      // 处理工作线程错误
      worker.on('error', (error) => {
        console.error('工作线程错误:', error)
        event.reply('txt-file-parsed', { success: false, error: error.message })
        worker.terminate()
        workers.delete(worker)
      })

      // 处理工作线程退出
      worker.on('exit', (code) => {
        if (code !== 0) {
          console.error(`工作线程退出，退出码: ${code}`)
        }
        workers.delete(worker)
      })
    }
  })

  // 处理文件选择请求
  ipcMain.handle('choose-file', async () => {
    try {
      // 打开文件选择对话框
      const result = await dialog.showOpenDialog({
        properties: ['openFile'],
        filters: [
          { name: 'Excel Files', extensions: ['xlsx', 'xls'] },
          { name: 'Text Files', extensions: ['txt'] }
        ]
      })

      if (result.canceled || result.filePaths.length === 0) {
        return { success: false, message: '未选择文件' }
      }

      const filePath = result.filePaths[0]
      console.log('选中的文件:', filePath)
      const fileExtension = filePath.split('.').pop().toLowerCase()
      let content = ''
      let lineCount = 0
      if (fileExtension === 'txt') {
        // 读取txt文件
        content = fs.readFileSync(filePath, 'utf8')
        lineCount = content.split('\n').length
      } else if (['xlsx', 'xls'].includes(fileExtension)) {
        // 读取excel文件
        const workbook = xlsx.readFile(filePath)
        const firstSheetName = workbook.SheetNames[0]
        const worksheet = workbook.Sheets[firstSheetName]
        const jsonData = xlsx.utils.sheet_to_json(worksheet, { header: 1 })
        lineCount = jsonData.length
        content = JSON.stringify(jsonData)
      }

      return {
        success: true,
        filePath: filePath,
        content: content,
        lineCount: lineCount
      }
    } catch (error) {
      console.error('选择文件时出错:', error)
      return { success: false, message: error.message }
    }
  })

  // 处理获取类目请求
  ipcMain.handle('get-leimu', async () => {
    try {
      // 在开发环境中，resources目录位于项目根目录
      // 在生产环境中，resources目录位于应用程序的资源目录
      const isDev = process.env.NODE_ENV === 'development'
      const filePath = isDev
        ? path.join(process.cwd(), 'resources', 'leimu.txt')
        : path.join(app.getPath('resources'), 'leimu.txt')
      console.log('读取类目文件:', filePath)
      const content = fs.readFileSync(filePath, 'utf8')
      const data = JSON.parse(content)
      return { success: true, data }
    } catch (error) {
      console.error('读取类目文件失败:', error)
      return { success: false, message: error.message }
    }
  })

  // 处理保存配置请求
  ipcMain.handle('save-config', async (event, { key, value }) => {
    console.log('保存配置:', key, value)
    try {
      const result = await saveConfig(db, key, value)
      return { success: true, result }
    } catch (error) {
      console.error('保存配置时出错:', error)
      return { success: false, message: error.message }
    }
  })

  // 处理加载配置请求
  ipcMain.handle('load-config', async (event, key) => {
    try {
      const value = await loadConfig(db, key)
      return { success: true, value }
    } catch (error) {
      console.error('加载配置时出错:', error)
      return { success: false, message: error.message }
    }
  })

  // 处理读取文件请求
  ipcMain.handle('read-file', async (event, filePath) => {
    try {
      const fs = require('fs')
      const path = require('path')
      const app = require('electron').app

      // 构建完整的文件路径
      const fullPath = path.join(app.getAppPath(), filePath)

      // 检查文件是否存在
      if (!fs.existsSync(fullPath)) {
        return {
          success: false,
          message: `文件不存在: ${fullPath}`
        }
      }

      // 读取文件内容
      const content = fs.readFileSync(fullPath, 'utf8')

      return {
        success: true,
        content: content
      }
    } catch (error) {
      console.error('读取文件失败:', error)
      return {
        success: false,
        message: error.message
      }
    }
  })

  // 处理保存文件请求
  ipcMain.handle('save-file', async (event, filePath, content) => {
    try {
      const fs = require('fs')
      const path = require('path')
      const app = require('electron').app

      // 构建完整的文件路径
      const fullPath = path.join(app.getAppPath(), filePath)

      // 写入文件内容
      fs.writeFileSync(fullPath, content, 'utf8')

      return {
        success: true,
        message: '文件保存成功'
      }
    } catch (error) {
      console.error('保存文件失败:', error)
      return {
        success: false,
        message: error.message
      }
    }
  })

  // 处理获取类目请求
  ipcMain.handle('get-diqu', async () => {
    try {
      // 在开发环境中，resources目录位于项目根目录
      // 在生产环境中，resources目录位于应用程序的资源目录
      const isDev = process.env.NODE_ENV === 'development'
      const filePath = isDev
        ? path.join(process.cwd(), 'resources', 'diqu.txt')
        : path.join(app.getPath('resources'), 'diqu.txt')
      console.log('读取地区文件:', filePath)
      const content = fs.readFileSync(filePath, 'utf8')
      const data = JSON.parse(content)
      return { success: true, data }
    } catch (error) {
      console.error('读取地区文件失败:', error)
      return { success: false, message: error.message }
    }
  })

  // 处理获取当前主题状态的请求
  ipcMain.handle('get-current-theme', async () => {
    try {
      const globalConfig = await loadConfig(db, 'globalConfig')
      if (globalConfig) {
        return {
          success: true,
          isDarkMode: JSON.parse(globalConfig).darkMode
        }
      } else {
        return {
          success: false,
          message: '主题未初始化',
          isDarkMode: false
        }
      }
    } catch (error) {
      console.error('获取主题状态失败:', error)
      return {
        success: false,
        message: error.message,
        isDarkMode: false
      }
    }
  })

  // 处理设置暗黑模式请求
  ipcMain.on('set-dark-mode', (event, isDarkMode) => {
    try {
      // 设置深色模式
      nativeTheme.themeSource = isDarkMode ? 'dark' : 'light'
      console.log('深色模式已', isDarkMode ? '启用' : '禁用')

      // 通知所有窗口主题已更改
      BrowserWindow.getAllWindows().forEach((window) => {
        window.webContents.send('theme-changed', isDarkMode)
      })
    } catch (error) {
      console.error('设置深色模式失败:', error)
    }
  })

  // 处理店铺导入请求
  ipcMain.handle('import-shop', async () => {
    try {
      // 打开文件选择对话框
      const result = await dialog.showOpenDialog({
        properties: ['openFile'],
        filters: [{ name: 'Excel Files', extensions: ['xlsx', 'xls'] }]
      })

      if (result.canceled || result.filePaths.length === 0) {
        throw new Error('未选择文件')
      }

      const filePath = result.filePaths[0]
      console.log('选中的Excel文件:', filePath)

      // 读取Excel文件
      const workbook = xlsx.readFile(filePath)
      // 获取第一个工作表
      const firstSheetName = workbook.SheetNames[0]
      const worksheet = workbook.Sheets[firstSheetName]

      // 转换为JSON数据
      const jsonData = xlsx.utils.sheet_to_json(worksheet, {
        header: 1, // 以数组形式返回，第一行作为数组的第一个元素
        raw: false // 格式化单元格值
      })

      // 提取第二行及以后的数据
      if (jsonData.length <= 1) {
        console.log('Excel文件中没有足够的数据')
        return []
      }

      const dataFromSecondRow = jsonData.slice(1)
      console.log('从第二行开始的数据:', dataFromSecondRow)
      // 写入到数据库
      dataFromSecondRow.forEach((item) => {
        let name = item[0]
        let pwd = item[1]

        // 查看name是否存在
        db.get('SELECT * FROM users WHERE name = ?', name, (err, row) => {
          if (err) {
            console.error('查询数据库错误:', err)
            return
          }
          if (row) {
            console.log('店铺已存在:', name)
          } else {
            console.log('店铺不存在:', name)

            // 添加店铺
            addUser(db, name, pwd)
          }
        })
      })
      return dataFromSecondRow
    } catch (error) {
      console.error('导入店铺数据时出错:', error)
      throw error
    }
  })

  createWindow()

  app.on('activate', function () {
    // On macOS it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

const getShopNameByNet = (result) => {
  return new Promise((resolve, reject) => {
    let url = 'https://h5api.m.taobao.com/h5/mtop.alibaba.shop.shopinfo.info.get/1.0/'
    // 获取毫秒数
    let time = new Date().getTime()
    let reqParams = '{"isFast":false}'
    let params1 = {
      jsv: '2.6.1',
      appKey: '12574478',
      t: time,
      sign: '',
      api: 'mtop.alibaba.shop.shopinfo.info.get',
      v: '1.0',
      ttid: '11320@taobao_WEB_9.9.99',
      dataType: 'originaljsonp',
      type: 'originaljsonp',
      callback: 'mtopjsonp19',
      data: reqParams
    }
    let token = ''
    result.cookie.split(';').forEach((item) => {
      let arr = item.split('=')
      if (arr[0].trim() == '_m_h5_tk') {
        token = arr[1].split('_')[0]
      }
    })
    let sign = `${token}&${time}&12574478&${reqParams}`
    console.log('sign:', sign)
    params1.sign = md5(sign)
    // 直接把params拼接到url上
    url += '?' + qs.stringify(params1)
    console.log('url:', url)
    // 使用fetch发送请求
    var myHeaders = new Headers()
    myHeaders.append('accept', '*/*')
    myHeaders.append('accept-language', 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6')
    myHeaders.append('cache-control', 'no-cache')
    myHeaders.append('pragma', 'no-cache')
    myHeaders.append('referer', 'https://qn.taobao.com/home.htm/shop-manage/shop-center')
    myHeaders.append(
      'sec-ch-ua',
      '"Chromium";v="134", "Not:A-Brand";v="24", "Microsoft Edge";v="134"'
    )
    myHeaders.append('sec-ch-ua-mobile', '?0')
    myHeaders.append('sec-ch-ua-platform', '"Windows"')
    myHeaders.append('sec-fetch-dest', 'script')
    myHeaders.append('sec-fetch-mode', 'no-cors')
    myHeaders.append('sec-fetch-site', 'same-site')
    myHeaders.append(
      'user-agent',
      'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Edg/134.0.0.0'
    )
    myHeaders.append('Cookie', result.cookie)

    console.log('Cookie:', result.cookie)
    var requestOptions = {
      method: 'GET',
      headers: myHeaders,
      redirect: 'follow'
    }

    fetch(url, requestOptions)
      .then((response) => {
        if (!response.ok) {
          throw new Error(`HTTP error! Status: ${response.status}`)
        }
        return response.text()
      })
      .then((data) => {
        // 尝试解析JSONP响应
        try {
          // 移除JSONP包装
          const jsonpData = data.replace(/^mtopjsonp19\((.*)\)$/, '$1')
          const parsedData = JSON.parse(jsonpData)
          resolve({
            success: true,
            data: parsedData,
            message: '获取店铺名称成功'
          })
        } catch (error) {
          resolve({
            success: true,
            data: data,
            message: '获取店铺名称成功，但解析失败',
            parseError: error.message
          })
        }
      })
      .catch((error) => {
        console.error('Error:', error)
        reject({
          success: false,
          data: null,
          message: '获取店铺名称失败',
          error: error.message
        })
      })
  })
}

const clearLoginUserStatus = () => {
  if (dev) {
    clearLogin(db).then((res) => {
      console.log('清除登录信息成功', res)
    })
  }
  // db.run('DELETE FROM "main"."tasks"')
  // db.run('DELETE FROM "main"."user_task"')
}
function deleteByValue(map, targetValue) {
  for (const [key, value] of map) {
    if (value === targetValue) {
      map.delete(key)
    }
  }
  return map
}

/**
 * 在数字上随机加减指定范围的数
 * @param {number} num - 原始数字
 * @param {number|Object} range - 可以传一个数字（如 `5` 表示 1~5），或者对象 `{ min, max }`
 * @returns {number}
 */
function randomAddOrSubtract(num, range) {
  // 处理 range 的传参方式
  let min, max
  if (typeof range === 'number') {
    min = 1
    max = range
  } else if (typeof range === 'object' && range.min !== undefined && range.max !== undefined) {
    min = range.min
    max = range.max
  } else {
    console.log('range 参数格式错误')
    throw new Error('range 必须是数字或 { min, max } 对象')
  }

  // 计算随机偏移量（在 min ~ max 之间随机）
  const offset = Math.floor(Math.random() * (max - min + 1)) + min
  // 50% 概率加或减
  const shouldAdd = Math.random() >= 0.5
  console.log('min:', min, 'max:', max, 'offset:', offset, 'num:', num, 'shouldAdd:', shouldAdd)
  return shouldAdd ? num + offset : num - offset
}

// 保留小数点后几位
const toFixedDecimal = (num, decimalPlaces) =>
  Math.round(num * 10 ** decimalPlaces) / 10 ** decimalPlaces

// 合并sku计算后的数组
const mergeArrays = (arr1, arr2) => {
  const map = new Map(arr1.map((item) => [item.skuid, item])) // arr1 转为 Map<skuid, obj>
  arr2.forEach((item) => map.set(item.skuid, item)) // arr2 覆盖相同 skuid
  return Array.from(map.values()) // 转回数组
}
